import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import java.util.ArrayList;
import java.util.List;


public class Player {
    private static final int WIDTH = GameWorld.GRID_SIZE;
    private static final int HEIGHT = GameWorld.GRID_SIZE;
    private static final float JUMP_FORCE = -8f; // 增加初始跳跃力
    private static final float GRAVITY = 0.5f; // 调整重力
    private static final float JUMP_ASCENT_TIME = GRAVITY / 1.2f; // 上升时间(秒)
    private static final float JUMP_CUT_MULTIPLIER = 0.5f; // 跳跃提前释放时的速度乘数
    private static final int ANIMATION_SPEED = 4;
    private static final float JUMP_TIME = 0.4f; // 总跳跃时间(秒)
    private float jumpTimeCounter = 0f;
    private boolean isJumping = false;
    private boolean isJumpCut = false; // 是否提前释放跳跃
    private boolean isJumpAscending = false; // 是否处于上升阶段
    // 滑铲相关属性
    protected boolean isSliding = false;
    private float slideTimeCounter = 0f;
    private static final float SLIDE_TIME = JUMP_TIME+0.1F; // 滑铲持续时间与跳跃相同
    private static final int SLIDE_HEIGHT = HEIGHT / 2; // 滑铲时高度减半
    // 滑铲过渡状态
    private boolean isSlideStarting = false;
    private float slideStartTime = 0f;
    private static final float SLIDE_START_DURATION = 0.1f; // 滑铲起始动画持续时间(秒)
    // 滑铲相关属性
    private static final float SLIDE_START_SCALE = 0.75f; // 滑铲起始状态缩放比例
    // 滑铲起始高度
    private static final int SLIDE_START_HEIGHT = (int)(HEIGHT * SLIDE_START_SCALE);
    private Image slideStartImage; // 滑铲起始图片
    private Image slideImage;      // 滑铲图片
    // 跳跃按键状态
    private boolean jumpKeyPressed = false;

    private int x;
    private int y;
    private float verticalVelocity = 0;

    private List<Image> walkFrames = new ArrayList<>();
    private int currentFrame = 0;
    private int frameCounter = 0;
    private List<Bomb> bombs = new ArrayList<>();
    private int bombAcount = 3;
    private long lastBombRecoveryTime = 0;
    private static final long BOMB_RECOVERY_INTERVAL = 1000; // 炸弹回复1秒一个
    private boolean isFallingIntoGap = false;  // 状态标识
    private static final float GAP_GRAVITY = 2.0f; // 缺口下落重力(比正常重力大)

    private boolean hasShield = false;
    private List<Image> walkFramesWithShield = new ArrayList<>();
    private Image slideStartImageWithShield;
    private Image slideImageWithShield;
    private boolean shieldHit = false; // 新增状态，表示护盾被击中
    private long shieldHitTime = 0; // 护盾被击中的时间
    private static final long SHIELD_HIT_DURATION = 500; // 护盾被击中后的无敌时间(毫秒)

    public boolean isShieldHit() {
        return shieldHit;
    }

    private boolean isFlying = false;
    private static final float FLY_SPEED = 5f;
    private Image broomImage;

    private long lastHitTime = 0;
    private static final long HIT_FLASH_DURATION = 500; // 被击中闪烁时间

    public boolean isHitFlashing() {
        return System.currentTimeMillis() - lastHitTime < HIT_FLASH_DURATION;
    }


    public void setShieldHit(boolean hit) {
        this.shieldHit = hit;
        if (hit) {
            this.shieldHitTime = System.currentTimeMillis();
        }
    }

    // 回复炸弹
    void updateBombRecovery(long currentTime) {
        // BOSS战中保持炸弹恢复
        long recoveryInterval = BOMB_RECOVERY_INTERVAL;
        if (currentTime - lastBombRecoveryTime >= recoveryInterval) {
            if (bombAcount < 6) {
                bombAcount++;
            }
            lastBombRecoveryTime = currentTime;
        }
    }

    public int getBombAcount() {
        return bombAcount;
    }

    public void setBombAcount() {
        if(this.bombAcount>0)
            this.bombAcount--;
    }


    public void throwBomb() {
        if (bombAcount <= 0 || bombs.size() >= 3) {
            return;
        }
        // 只在成功创建炸弹后减少数量
        Bomb bomb = new Bomb(x + WIDTH, y + HEIGHT/2, 3 * GameWorld.GROUND_SPEED);
        bombs.add(bomb);
    }


    public Player(int x, int y) {
        this.x = x;
        this.y = GameConstants.getScreenHeight() - GameWorld.GRID_SIZE * 2;
        loadImages(); // 确保在构造函数中加载图像
    }

    private void loadImages() {
        try {
            walkFrames = new ArrayList<>();
            for (int i = 1; i <= 12; i++) {
                String path = String.format("/images/hero%d.png", i);
                walkFrames.add(new Image(getClass().getResourceAsStream(path)));
            }
            // 加载滑铲相关图片
            slideStartImage = new Image(getClass().getResourceAsStream("/images/Slide_shovel1.png"));
            slideImage = new Image(getClass().getResourceAsStream("/images/Slide_shovel2.png"));
            broomImage = new Image(getClass().getResourceAsStream("/images/hero_broom.png"));

            // 加载带护盾的图像
            for (int i = 1; i <= 12; i++) {
                String path = String.format("/images/hero%dU.png", i);
                walkFramesWithShield.add(new Image(getClass().getResourceAsStream(path)));
            }
            slideStartImageWithShield = new Image(getClass().getResourceAsStream("/images/Slide_shovel1U.png"));
            slideImageWithShield = new Image(getClass().getResourceAsStream("/images/Slide_shovel2U.png"));

        } catch (Exception e) {
            System.err.println("加载玩家图像资源失败: " + e.getMessage());
            System.exit(1);
        }
    }

    public void update(double deltaTime, GameWorld world) {
        if (GameConstants.GAME_PAUSED) {
            return; // 游戏暂停时不更新玩家状态
        }

        // 检查护盾被击中状态是否结束
        if (shieldHit && System.currentTimeMillis() - shieldHitTime > SHIELD_HIT_DURATION) {
            shieldHit = false;
            useShield(); // 真正移除护盾
        }

        // 检查是否进入BOSS战
        if (world.isBossFightActive() && !isFlying) {
            isFlying = true;
            hasShield = true; // 进入无敌状态
        }
        updateBombRecovery(System.currentTimeMillis());

        // BOSS战结束后恢复地面状态
        if (!world.isBossFightActive() && isFlying) {
            isFlying = false;
            hasShield = false;
            y = world.getGroundY() - HEIGHT; // 落回地面
        }

        // 飞行模式控制
        if (isFlying) {
            // 保持玩家在屏幕中间80%区域
            int minY = (int)(GameConstants.getScreenHeight() * 0.1);
            int maxY = (int)(GameConstants.getScreenHeight() * 0.9 - HEIGHT);

            // 上下移动
            if (jumpKeyPressed) { // W键上升
                y -= FLY_SPEED * deltaTime * 60;
            } else if (isSliding) { // S键下降
                y += FLY_SPEED * deltaTime * 60;
            }

            // 限制边界
            if (y < minY) y = minY;
            if (y > maxY) y = maxY;

            // 更新炸弹
            for (int i = 0; i < bombs.size(); i++) {
                Bomb bomb = bombs.get(i);
                bomb.update();

                if (!bomb.exploding && world.getBoss().checkHit(bomb)) {
                    bomb.explode();
                }

                if (!bomb.active) {
                    bombs.remove(i);
                    i--;
                }
            }

            return; // 飞行模式下跳过普通物理更新
        }



        // 检查是否捡到护盾
        if (!hasShield && world.checkShieldCollision(x, y, WIDTH, getHeight())) {
            hasShield = true;
        }

        updateBombRecovery(System.currentTimeMillis());

        // 更新动画帧
        frameCounter++;
        if (frameCounter >= ANIMATION_SPEED) {
            frameCounter = 0;
            currentFrame = (currentFrame + 1) % 12;
        }

        // 处理滑铲起始状态
        if (isSlideStarting) {
            slideStartTime += deltaTime;
            if (slideStartTime >= SLIDE_START_DURATION) {
                isSlideStarting = false;
                isSliding = true;
                slideTimeCounter = 0f;
            }
        }

        // 检查是否站在实心地面
        boolean onSolidGround = world.isSolidGround(x + WIDTH/2, y + HEIGHT);

        // 如果不在跳跃状态且不站在实心地面，则开始下落
        if (!isJumping && !onSolidGround) {
            isJumping = true;
            isFallingIntoGap = true;  // 标记为缺口下落
            verticalVelocity = 0;
        }

        // 更新滑铲计时器
        if (isSliding) {
            slideTimeCounter += deltaTime;
            if (slideTimeCounter >= SLIDE_TIME) {
                endSlide();
            }
        }

        // 如果在滑铲中按下跳跃键
        if ((isSliding || isSlideStarting) && jumpKeyPressed) {
            endSlide();
            jump();
        }

        // 处理跳跃/下落物理
        if (isJumping) {
            // 根据状态选择重力系数
            float currentGravity = isFallingIntoGap ? GAP_GRAVITY : GRAVITY;

//            verticalVelocity += currentGravity;
//            y += verticalVelocity;

            // 跳跃时间控制
            if (isJumping && !isJumpCut) {
                jumpTimeCounter += deltaTime;
                // 判断跳跃阶段
                if (jumpTimeCounter <= JUMP_ASCENT_TIME) {
                    isJumpAscending = true;
                } else {
                    isJumpAscending = false;
                }

                if (jumpTimeCounter > JUMP_TIME) {
                    isJumpCut = true;
                }
            }

            // 应用跳跃力或重力
            if (isJumpAscending && !isJumpCut) {
                // 上升阶段 - 应用向上的力
                verticalVelocity = JUMP_FORCE * (1 - (jumpTimeCounter / JUMP_ASCENT_TIME));
            } else {
                // 下落阶段 - 应用重力
                verticalVelocity += currentGravity * 0.3;
            }

            y += verticalVelocity * deltaTime * 60;

            // 检查是否落在实心地面上
            if (y >= world.getGroundY() - HEIGHT && world.isSolidGround(x + WIDTH/2, y + HEIGHT)) {
                y = world.getGroundY() - HEIGHT;
                isJumping = false;
                isFallingIntoGap = false;  // 重置状态
                verticalVelocity = 0;
                jumpTimeCounter = 0f;
                isJumpAscending = false;
            }
        }

        // 更新炸弹
        for (int i = 0; i < bombs.size(); i++) {
            Bomb bomb = bombs.get(i);
            bomb.update();

            if (!bomb.exploding && world.checkBombCollision(bomb)) {
                bomb.explode();
            }

            if (!bomb.active) {
                bombs.remove(i);
                i--;
            }
        }
    }

    public boolean isInvincible() {
        // 被击中后的无敌时间或护盾被击中时
        return (System.currentTimeMillis() - lastHitTime < HIT_FLASH_DURATION) ||
                (hasShield && shieldHit);
    }

    public void setHitByBoss() {
        if (!isInvincible()) {
            lastHitTime = System.currentTimeMillis();
            if (hasShield) {
                setShieldHit(true);
            }
        }
    }

    // 添加设置跳跃按键状态的方法
    public void setJumpKeyPressed(boolean pressed) {
        this.jumpKeyPressed = pressed;
    }

    public boolean hasLandedOnVoid(GameWorld world) {
        // 只有当不跳跃且站在虚空上才返回true
        return !isJumping && y >= world.getGroundY() - HEIGHT &&
                !world.isSolidGround(x + WIDTH/2, y + HEIGHT);
    }

    public void slide() {
        if (!isSliding && !isSlideStarting && !isJumping) {
            isSlideStarting = true;
            slideStartTime = 0f;
        }
    }

    // 结束滑铲
    public void endSlide() {
        isSlideStarting = false;
        isSliding = false;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getWidth() {
        return WIDTH;
    }

    public int getHeight() {
        if (isSliding) {
            return SLIDE_HEIGHT; // 完全滑铲状态高度减半
        } else if (isSlideStarting) {
            return SLIDE_START_HEIGHT; // 滑铲起始状态高度为3/4
        }
        return HEIGHT; // 正常状态
    }

    public void render(GraphicsContext gc) {
        if (isHitFlashing() && (System.currentTimeMillis() - lastHitTime) % 200 < 100) {
            return;
        }
        if (walkFrames == null || walkFrames.isEmpty()) {
            return;
        }

        if (isFlying) {
            gc.drawImage(broomImage, x, y, WIDTH, HEIGHT);
            return;
        }

        // 护盾被击中时不渲染（创建闪烁效果）
        if (isShieldHit() && (System.currentTimeMillis() - shieldHitTime) % 200 < 100) {
            return;
        }

        // 渲染炸弹
        for (Bomb bomb : bombs) {
            bomb.render(gc);
        }

        // 根据是否有护盾选择图像集
        List<Image> currentWalkFrames = hasShield ? walkFramesWithShield : walkFrames;
        Image currentSlideStartImage = hasShield ? slideStartImageWithShield : slideStartImage;
        Image currentSlideImage = hasShield ? slideImageWithShield : slideImage;

        // 根据状态选择图像
        Image playerImage;
        if (isJumping) {
            playerImage = currentWalkFrames.get(10);
        } else if (isSlideStarting) {
            playerImage = currentSlideStartImage; // 滑铲起始图片
        } else if (isSliding) {
            playerImage = currentSlideImage; // 完全滑铲图片
        } else {
            playerImage = currentWalkFrames.get(currentFrame);
        }


        // 计算渲染尺寸和位置
        float renderWidth, renderHeight, renderX, renderY;

        if (isSlideStarting) {
            // 滑铲起始状态：图像缩小为3/4
            renderWidth = WIDTH * SLIDE_START_SCALE;
            renderHeight = HEIGHT * SLIDE_START_SCALE;
            renderX = x + (WIDTH - renderWidth) / 2; // 居中显示
            renderY = y + (HEIGHT - renderHeight); // 底部对齐
        } else if (isSliding) {
            // 完全滑铲状态
            renderWidth = WIDTH;
            renderHeight = SLIDE_HEIGHT;
            renderX = x;
            renderY = y + (HEIGHT - SLIDE_HEIGHT);
        } else {
            // 正常状态
            renderWidth = WIDTH;
            renderHeight = HEIGHT;
            renderX = x;
            renderY = y;
        }

        gc.drawImage(playerImage, renderX, renderY, renderWidth, renderHeight);
    }

    // 添加护盾状态检查
    public boolean hasShield() {
        return hasShield;
    }

    // 使用护盾
    public void useShield() {
        hasShield = false;
    }

    public void jump() {
        if (!isJumping) {
            isJumping = true;
            isJumpCut = false;
            isJumpAscending = true;
            jumpTimeCounter = 0f;
            verticalVelocity = JUMP_FORCE;
        }
    }

    public void endJump() {
        if (isJumping && !isJumpCut) {
            isJumpCut = true;
            isJumpAscending = false;
            verticalVelocity *= JUMP_CUT_MULTIPLIER;
        }
    }

    public boolean isJumping() {
        return isJumping;
    }

    public boolean isSliding() {
        return isSliding || isSlideStarting;
    }


    public void reset() {
        this.y = GameConstants.getScreenHeight() - GameWorld.GRID_SIZE * 2;
        isJumping = false;
        verticalVelocity = 0;
        bombAcount = 6;
        lastBombRecoveryTime = System.currentTimeMillis();
        isFallingIntoGap = false;
        hasShield = false;
    }

    public void renderBombs(GraphicsContext gc) {
        for (Bomb bomb : bombs) {
            bomb.render(gc);
        }
    }


    public List<Bomb> getBombs() {
        return bombs;
    }

    public void setSliding(boolean b) {
        isSliding=b;
    }
}